<?php

namespace app\admin\model;

use think\db\exception\DbException;
use think\facade\Log;
use think\Model;
use think\model\concern\SoftDelete;
use think\model\relation\HasMany;
use think\model\relation\HasOne;

/**
 * Order
 * @controllerUrl 'order'
 * @property int|mixed user_id
 * @property string|mixed order_sn
 * @property string username
 * @property string|mixed channel
 * @property string|mixed mobile
 * @property string|mixed address
 * @property float|mixed total_price
 * @property float|mixed post_price
 * @property float|mixed discount
 * @property float|mixed pay_price
 * @property float|mixed score_money
 * @property int|mixed coupon_id
 * @property float|mixed coupon_price
 * @property string|mixed pay_type
 * @property int|mixed pay_time
 * @property string|mixed remark
 * @property int|mixed state
 * @property int|mixed id
 * @property string|mixed transaction_id
 * @property int|mixed use_score
 * @property string commission
 * @property string datas
 * @property User $user
 * @property OrderGoods[] $orderGoods
 * @property OrderGoods[] $orderGoods2
 */
class Order extends Model
{
    use SoftDelete;

    // 表名
    protected $name = 'order';
    protected array $stateList = [
        0 => '待支付',
        1 => '已支付',
        2 => '待收货',
        3 => '已完成',
        4 => '退款中',
        5 => '已退款',
        6 => '支付超时',
        7 => '取消订单',
    ];

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';

    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $dateFormat = 'Y-m-d H:i:s';

    protected $type = [
        'pay_time' => 'timestamp:Y-m-d H:i:s',
        'delete_time' => 'timestamp:Y-m-d H:i:s',
    ];


    public function getUserIdAttr($value, $row)
    {
        return !$value ? '' : $value;
    }

    /**
     * 获取唯一订单号
     * @return string
     * @throws DbException
     */
    public function getOrderSn(): string
    {
        try {
            [$micro, $time] = explode(' ', microtime());
            $micro = explode('.', sprintf('%.6f', $micro));
            $micro = $micro[1];
        } catch (\Exception $e) {
            $micro = rand(100000, 999999);
        }
        $orderSn = date('YmdHis') . $micro . rand(1000, 9999);
        $hasSn = $this->where('order_sn', $orderSn)->count();
        if ($hasSn > 0) {
            return $this->getOrderSn();
        }
        return $orderSn;
    }

    public function user(): HasOne
    {
        return $this->hasOne(User::class, 'id', 'user_id');
    }

    public function orderGoods(): HasMany
    {
        return $this->hasMany(OrderGoods::class, 'order_id', 'id');
    }

    public function paySuccess($message): bool
    {
        try {
            $order = $this->with(['user', 'orderGoods.goods'])->where('order_sn', $message['out_trade_no'])->find();
            if (!$order) {
                Log::error($message['out_trade_no'] . '不存在');
                return false;
            }
            if ($order->pay_time > 0 || $order->state != 0) {
                Log::error($message['out_trade_no'] . '已支付');
                return false;
            }
            if (isset($message['sign'])) unset($message['sign']);
            $order->datas = json_encode($message, JSON_UNESCAPED_UNICODE);
            $this->startTrans();
            // 订单设为已支付
            $order->state = 1;
            $order->pay_time = time();
            $order->transaction_id = $message['transaction_id'];
            // 用户支付次数和支付金额
            if (!$order->user) {
                Log::error('用户' . $order->user_id . '不存在');
                return false;
            }
            $order->user->pay_count += 1;
            $order->user->pay_money += $order->pay_price;
            // 开始分成
            $parentTree = $order->user->getParentTree($order->user->pid);
            $commission = [];
            $moneyLog = new UserMoneyLog();
            $score = 0;
            foreach ($order->orderGoods as $orderGoods) {
                // 赠送优惠券
                if (count($orderGoods->goods->coupon_ids) > 0) {
                    $coupons = [];
                    foreach ($orderGoods->goods->coupon_ids as $coupon_id) {
                        $coupon = Coupon::find($coupon_id);
                        if ($coupon) {
                            $coupons[] = [
                                'user_id' => $order->user->id,
                                'coupon_id' => $coupon->id,
                                'updatetime' => 0
                            ];
                        }
                    }
                    $userCoupon = new UserCoupon();
                    $userCoupon->saveAll($coupons);
                }
                $orderGoods->goods->sales += $orderGoods->total;
                $orderGoods->goods->save();
                $score += $orderGoods->goods->integral;
                $userScore = new UserScoreLog();
                $userScore->save([
                    'user_id' => $order->user->id,
                    'score' => $score,
                    'before' => $order->user->score,
                    'after' => $order->user->score + $score,
                    'memo' => "购买商品「{$orderGoods->goods->goods_name}[{$orderGoods->attr_name}]」",
                ]);
                $commissionList = [
                    $orderGoods->goods->commission1 ?: (get_sys_config('commission1') ?: 0),
                    $orderGoods->goods->commission2 ?: (get_sys_config('commission2') ?: 0),
                    $orderGoods->goods->commission3 ?: (get_sys_config('commission3') ?: 0),
                ];
                foreach ($parentTree as $k => $parent) {
                    if (strstr($commissionList[$k], '%')) {
                        $commissionList[$k] = sprintf('%.2f', str_replace('%', '', $commissionList[$k])) / 100;
                        $price = (float)bcmul($commissionList[$k], $orderGoods->price, 2);
                    } else {
                        $commissionList[$k] = floatval($commissionList[$k]);
                        $price = $commissionList[$k];
                    }
                    $commission[] = ["上级用户:{$parent->id};分佣比例:{$commissionList[$k]};商品价格:{$orderGoods->price};获得佣金:{$price};"];
                    $moneyLog->create([
                        'user_id' => $parent->id,
                        'money' => $price,
                        'memo' => "购买商品「{$orderGoods->goods->goods_name}[{$orderGoods->attr_name}]」",
                    ]);
                    $parent->save();
                }
            }
            $order->commission = json_encode($commission, JSON_UNESCAPED_UNICODE);
            // 赠送积分
            if ($score > 0) {
                $order->user->score = $order->user->score + $score;
            }
            $order->user->save();
            $order->save();
            $order->user->upgrade($order->user->id);
            $this->commit();
            return true;
        } catch (\Exception $e) {
            Log::error($e->getFile() . ':' . $e->getLine() . '=>' . $e->getMessage());
            Log::error($e->getTraceAsString());
            return false;
        }
    }

    public function getStateTxt($state)
    {
        return $this->stateList[$state] ?? '未知';
    }
}